#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
RVGDM: RISC-V Godot 版本管理工具，用于管理 RISC-V 架构下的 Godot 引擎版本，支持编辑器、导出模板的安装和卸载。

MIT License Copyright (c) 2025 DSOE1024
"""

import os
import json
import argparse
import shutil
import subprocess
import sys
from urllib.request import urlopen
from urllib.error import HTTPError
from pathlib import Path

VERSION = "0.1.0"
GDVM_DIR = os.path.expanduser("~/.rvgdvm")
VERSIONS_DIR = os.path.join(GDVM_DIR, "versions")
CONFIG_FILE = os.path.join(GDVM_DIR, "release.json")
RELEASE_JSON_URL = "https://gitee.com/openkylin/godot-riscv/raw/master/release.json"

# 国际化配置
LOCALES = {
    'en': {
        'version_not_found': "Version {version} not found",
        'version_exists': "Version {version} already installed",
        'download_complete': "Download complete",
        'download_failed': "Download failed: {reason}",
        'installed': "Installed {version}",
        'version_uninstalled': "Uninstalled {version}",
        'list_title': "Installed versions:",
        'template_installed': "Template {version} installed",
        'template_uninstalled': "Template {version} uninstalled",
        'extracting': "Extracting...",
        'downloading': "Downloading...",
        'info_title': "RVGDM: RISC-V Godot Version Manager",
        'info_godot_version': "Version:",
        'info_godot_dir': "Godot directory:",
        'list_remote_title': "Remote versions:",
        'downloading_release_template': "Downloading release template...",
        'downloading_debug_template': "Downloading debug template...",
        'template_exists': "Template {version} already exists",
        'template_not_found': "Template {version} not found",
        'downloading_editor': "Downloading editor...",
        'template_extract_failed': "Template extraction failed: {reason}",
        'start_failed': "Failed to start Godot: {reason}"
    },
    'zh_CN': {
        'version_not_found': "版本 {version} 未找到",
        'version_exists': "版本 {version} 已安装",
        'download_complete': "下载完成",
        'download_failed': "下载失败: {reason}",
        'installed': "已安装 {version}",
        'version_uninstalled': "已卸载 {version}",
        'list_title': "已安装版本:",
        'template_installed': "导出模板 {version} 已安装",
        'template_uninstalled': "导出模板 {version} 已卸载",
        'extracting': "解压中...",
        'downloading': "下载中...",
        'info_title': "RVGDM: RISC-V Godot 版本管理器",
        'info_godot_version': "版本: {version}",
        'info_godot_dir': "Godot 引擎目录: {dir}",
        'list_remote_title': "远程可用的版本:",
        'downloading_release_template': "下载Release导出模板...",
        'downloading_debug_template': "下载Debug导出模板...",
        'template_exists': "导出模板 {version} 已存在",
        'template_not_found': "导出模板 {version} 未找到",
        'downloading_editor': "下载编辑器...",
        'template_extract_failed': "导出模板解压失败: {reason}",
        'start_failed': "启动 Godot 失败: {reason}"
    }
    # TODO：添加更多语言支持
}


# 检测当前语言
def detect_lang():
    # 获取环境变量LANG的值
    lang = os.environ.get('LANG', 'en').split('.')[0].lower()
    if lang.startswith('zh_cn'):
        return 'zh_CN'
    else:
        return 'en'


CURRENT_LANG = detect_lang()

# 国际化函数
def t(key, **kwargs):
    return LOCALES[CURRENT_LANG].get(key, key).format(**kwargs)


def ensure_dirs():
    os.makedirs(VERSIONS_DIR, exist_ok=True)

def get_release_data():
    try:
        with urlopen(RELEASE_JSON_URL) as response:
            data = response.read()
        # 解析JSON数据
        release_data = json.loads(data)
        return release_data
    except Exception as e:
        print(f"Error fetching release data: {e}")
        return None


def download_file(url, file_path):
    try:
        with urlopen(url) as response:
            total_size = int(response.headers.get('Content-Length', 0))
            downloaded = 0
            chunk_size = 8192
        
            with open(file_path, 'wb') as f:
                while True:
                    chunk = response.read(chunk_size)
                    if not chunk: 
                        break
                    f.write(chunk)
                    downloaded += len(chunk)
                    
                    # 进度计算
                    if total_size > 0:
                        done = int(50 * downloaded / total_size)
                        percent = (downloaded / total_size) * 100
                    else:
                        done = 0
                        percent = 0
                    
                    # 构建显示内容
                    percent_str = f"{percent:.1f}%" if total_size > 0 else "---%"
                    
                    # 更新进度条
                    print(
                        f"\r[{'#' * done}{'.' * (50 - done)}] {percent_str} {downloaded/1e6:.1f}MB", 
                        end='',
                        flush=True
                    )
        return True
    except Exception as e:
        raise


# 安装指定版本的编辑器
def install_version(version):
    data = get_release_data()
    if version not in data:
        print(t('version_not_found', version=version))
        return
    
    url = data[version]['download_url']
    version_dir = os.path.join(VERSIONS_DIR, version)
    if os.path.exists(version_dir):
        print(t('version_exists', version=version))
        return
    
    os.makedirs(version_dir, exist_ok=True)
    zip_file = os.path.join(version_dir, "package.7z")
    
    # 下载

    try:
        print("\n" + t('downloading_editor'))
        download_file(url, zip_file)
        print("\n" + t('download_complete'))
    except HTTPError as e:
        print("\n" + t('download_failed', reason=f"{e.code} {e.reason}"))
        if os.path.exists(zip_file):
            os.remove(zip_file)
        return
    # 解压
    subprocess.run(["7zr", "x", zip_file, f"-o{version_dir}"], check=True)

    # 给与可执行权限chmod +x
    # subprocess.run(["chmod", "+x", f"{version_dir}/godot.linuxbsd.editor.rv64.llvm"], check=True)

    os.remove(zip_file)
    
    for f in os.listdir(version_dir):
        if f.startswith("godot"):
            os.chmod(os.path.join(version_dir, f), 0o755)
            # 给与可执行权限chmod +x
            subprocess.run(["chmod", "+x", os.path.join(version_dir, f)], check=True)
            print(t('installed', version=version))
            return

# 卸载指定版本的编辑器
def uninstall_version(version):
    version_dir = os.path.join(VERSIONS_DIR, version)
    if not os.path.exists(version_dir):
        print(t('version_not_found', version=version))
        return

    shutil.rmtree(version_dir)
    print(t('version_uninstalled', version=version))

# 启动指定版本的编辑器
def start_version(version):
    version_dir = os.path.join(VERSIONS_DIR, version)
    if not os.path.exists(version_dir):
        print(t('version_not_found', version=version))
        return
    for f in os.listdir(version_dir):
        if f.startswith("godot"):
            try:
                """
                根据不同GPU环境选择不同的启动方式，由于大部分RISC-V板卡使用的是PVR的GPU，所以需要特殊处理，更多情况还需要进一步处理验证
                Godot启动参数参考：https://docs.godotengine.org/zh-cn/4.x/tutorials/editor/command_line_tutorial.html
                """
                # 获取系统$XDG_SESSION_TYPE的值
                xdg_session_type = os.environ.get('XDG_SESSION_TYPE', 'unknown')
                if xdg_session_type == 'wayland':
                    """
                    通过 $MESA_LOADER_DRIVER_OVERRIDE 获取是否是 pvr
                    """
                    if os.environ.get('MESA_LOADER_DRIVER_OVERRIDE', '') == 'pvr':
                        print(t('start_with_opengl_es3', version=version))
                        subprocess.Popen([os.path.join(version_dir, f), "--display-driver wayland opengl_es3"], start_new_session=True)
                    else:
                        subprocess.Popen([os.path.join(version_dir, f)], start_new_session=True)
                elif xdg_session_type == 'x11':
                    subprocess.Popen([os.path.join(version_dir, f)], start_new_session=True)
                elif xdg_session_type == 'unknown' or xdg_session_type == 'tty':
                    print(t('start_with_headless', version=version))
                    subprocess.Popen([os.path.join(version_dir, f), "--headless"], start_new_session=True)
                else:
                    subprocess.Popen([os.path.join(version_dir, f)], start_new_session=True)
                return
            except Exception as e:
                print(t('start_failed', version=version, reason=str(e)))
                return


# 列出本地安装的版本
def list_versions():
    print(t('list_title'))
    for v in os.listdir(VERSIONS_DIR):
        print(f" - {v}")

# 列出远程可用的版本
def list_remote_versions():
    print(t('list_remote_title'))
    data = get_release_data()
    for version in data:
        print(f" - {version}")


# 安装导出模板
def install_template(version):
    template_dir = Path.home() / ".local" / "share" / "godot" / "export_templates" / f"{version}.stable"
    os.makedirs(template_dir, exist_ok=True)

    # 检查是否有linux_release.rv64和linux_debug.rv64
    if os.path.exists(template_dir / "linux_release.rv64") and os.path.exists(template_dir / "linux_debug.rv64"):
        print(t('template_exists', version=version))
        return
    # 不完整的模板，删除
    elif os.path.exists(template_dir / "linux_release.rv64"):
        os.remove(template_dir / "linux_release.rv64")
    elif os.path.exists(template_dir / "linux_debug.rv64"):
        os.remove(template_dir / "linux_debug.rv64")

    data = get_release_data()
    rt_url = data[version]['release_template_url']
    dt_url = data[version]['debug_template_url']
    
    rt_tmp_file = "/tmp/rt_template.7z"
    dt_tmp_file = "/tmp/dt_template.7z"
    
    try:
        print("\n" + t('downloading_release_template'))
        download_file(rt_url, rt_tmp_file)
        print("\n" + t('download_complete'))
    except HTTPError as e:
        print("\n" + t('download_failed', reason=f"{e.code} {e.reason}"))
        if os.path.exists(rt_tmp_file):
            os.remove(rt_tmp_file)
        return

    try:
        print("\n" + t('downloading_debug_template'))
        download_file(dt_url, dt_tmp_file)
        print("\n" + t('download_complete'))
    except HTTPError as e:
        print("\n" + t('download_failed', reason=f"{e.code} {e.reason}"))
        if os.path.exists(dt_tmp_file):
            os.remove(dt_tmp_file)
        return
    

    # 解压
    try:
        subprocess.run(["7zr", "x", rt_tmp_file, f"-o{template_dir}"], check=True)
    except Exception as e:
        print(t('template_extract_failed', reason=str(e)))
        return
    finally:
        os.remove(rt_tmp_file)
    
    try:
        subprocess.run(["7zr", "x", dt_tmp_file, f"-o{template_dir}"], check=True)
    except Exception as e:
        print(t('template_extract_failed', reason=str(e)))
        return
    finally:
        os.remove(dt_tmp_file)

    # 重命名为 linux_release.rv64
    os.rename(template_dir / "godot.linuxbsd.template_release.rv64.llvm", template_dir / "linux_release.rv64")

    # 重命名为 linux_debug.rv64
    os.rename(template_dir / "godot.linuxbsd.template_debug.rv64.llvm", template_dir / "linux_debug.rv64")

    # chmod +x
    subprocess.run(["chmod", "+x", template_dir / "linux_release.rv64"])
    subprocess.run(["chmod", "+x", template_dir / "linux_debug.rv64"])

    print(t('template_installed', version=version))

# 卸载导出模板
def uninstall_template(version):
    template_dir = Path.home() / ".local" / "share" / "godot" / "export_templates" / f"{version}-stable"
    if not os.path.exists(template_dir):
        print(t('template_not_found', version=version))
        return

    shutil.rmtree(template_dir)
    print(t('template_uninstalled', version=version))

# 打印信息
def print_info():
    print(t('info_title'))
    print(t('info_godot_version', version=VERSION))
    print(t('info_godot_dir', dir=VERSIONS_DIR))

def main():
    parser = argparse.ArgumentParser(prog='rvgdvm')
    subparsers = parser.add_subparsers(dest='command')
    
    install_parser = subparsers.add_parser('install')
    install_parser.add_argument('version')

    uninstall_parser = subparsers.add_parser('uninstall')
    uninstall_parser.add_argument('version')
    
    start_parser = subparsers.add_parser('start')
    start_parser.add_argument('version')
    
    list_parser = subparsers.add_parser('list')

    list_remote_parser = subparsers.add_parser('list-remote')

    template_parser = subparsers.add_parser('install-template')
    template_parser.add_argument('version')

    uninstall_template_parser = subparsers.add_parser('uninstall-template')
    uninstall_template_parser.add_argument('version')

    info_parser = subparsers.add_parser('info')
    
    args = parser.parse_args()
    
    ensure_dirs()
    
    if args.command == 'install':
        install_version(args.version)
    elif args.command == 'uninstall':
        uninstall_version(args.version)
    elif args.command == 'start':
        start_version(args.version)
    elif args.command == 'list':
        list_versions()
    elif args.command == 'list-remote':
        list_remote_versions()
    elif args.command == 'install-template':
        install_template(args.version)
    elif args.command == 'uninstall-template':
        uninstall_template(args.version)
    elif args.command == 'info':
        print_info()
    else:
        parser.print_help()

if __name__ == '__main__':
    # 处理CTL+C退出
    try:
        main()
    except KeyboardInterrupt:
        print("\n" + t('exit'))
        sys.exit(0)
        # 退出后删除未完成的下载文件
    except Exception as e:
        print(f"\n{t('error')}: {e}")
        sys.exit(1)
